#include "tablemodel.h"
#include <QThread>

TableModel::TableModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    enAddrFormat = FORMAT_HEX;
    enFirstFormat = FORMAT_HEX;
    enSecFormat = FORMAT_CHAR;
    enFirstEndian = LITTLE_ENDIAN;
    enSecEndian = LITTLE_ENDIAN;
}


TableModel::~TableModel()
{
}

QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal)
    {    //水平表头
        if (role == Qt::DisplayRole)
        {  //角色为显示
            if (section == 0)
            {
                return "Addr";  //返回指定位置表头
            }
            else if (section == 33)
            {
                return QVariant();
            }
            else
            {
                return QString::number((section - 1) % 16, 16).toUpper();
            }
        }
    }

    return QAbstractTableModel::headerData(section, orientation, role);
}

int TableModel::rowCount(const QModelIndex & parent) const
{
    return this->array.length() / 16 + 1;
}

int	TableModel::columnCount(const QModelIndex & parent) const
{
    return 1 + 16 + 16 + 1;
}

QVariant TableModel::data(const QModelIndex & index, int role) const
{
    if (!index.isValid())
    {
        return QVariant();
    }

    if (role != Qt::DisplayRole)
    {
        return QVariant();
    }

    if (index.column() == 33)
    {
        return QVariant();
    }

    if (index.column() == 0)
    {
        int line = index.row();
        int addr = line * 16;


        if (enAddrFormat == FORMAT_OCT)
        {
            QString str = QString("%1").arg(addr, 7, 8, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else if (enAddrFormat == FORMAT_DEC)
        {
            QString str = QString("%1").arg(addr, 7, 10, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else
        {
            QString str = QString("%1").arg(addr, 7, 16, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }

    }

    int pos = 0;

    if (index.column() > 16)
    {
        pos = (index.row()) * 16 + index.column() - 1 - 16;
    }
    else
    {
        pos = (index.row()) * 16 + index.column() - 1;
    }

    if (pos >= this->array.length())
    {
        return QVariant();
    }

    if (index.column() > 16)
    {
        if (enSecFormat == FORMAT_HEX)
        {
            unsigned char c = (unsigned char)this->array.at(pos);
            QString str = QString("%1").arg(c, 2, 16, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else if (enSecFormat == FORMAT_DEC)
        {
            char c = (unsigned char)this->array.at(pos);
            return QVariant(QString::number(c, 10).toUpper());
        }
        else if (enSecFormat == FORMAT_OCT)
        {
            unsigned char c = (unsigned char)this->array.at(pos);
            QString str = QString("%1").arg(c, 3, 8, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else if (enSecFormat == FORMAT_BIN)
        {
            unsigned char c = (unsigned char)this->array.at(pos);
            QString str = QString("%1").arg(c, 8, 2, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else
        {
            if (this->array.at(pos) > 0)
            {
                return QVariant(QString(this->array.at(pos)));
            }
            else
            {
                return QString(".");
            }
        }
    }
    else
    {
        if (enFirstFormat == FORMAT_HEX)
        {
            unsigned char c = (unsigned char)this->array.at(pos);
            QString str = QString("%1").arg(c, 2, 16, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else if (enFirstFormat == FORMAT_DEC)
        {
            char c = (unsigned char)this->array.at(pos);
            return QVariant(QString::number(c, 10).toUpper());
        }
        else if (enFirstFormat == FORMAT_OCT)
        {
            unsigned char c = (unsigned char)this->array.at(pos);
            QString str = QString("%1").arg(c, 3, 8, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else if (enFirstFormat == FORMAT_BIN)
        {
            unsigned char c = (unsigned char)this->array.at(pos);

            QString str = QString("%1").arg(c, 8, 2, QLatin1Char('0')).toUpper();
            return QVariant(str);
        }
        else
        {
            if (this->array.at(pos) > 0)
            {
                return QVariant(QString(this->array.at(pos)));
            }
            else
            {
                return QString(".");
            }
        }
    }
}

void TableModel::setData(QByteArray array)
{
    beginResetModel();
    this->array = array;
    endResetModel();
}


QByteArray TableModel::getBytes(const QModelIndex & index, int length)
{
    if (!index.isValid())
    {
        return QByteArray();
    }

    if (index.column() < 1 || index.column() > 17)
    {
        return QByteArray();
    }

    int pos = 0;
    pos = (index.row()) * 16 + index.column() - 1;

    QByteArray a;
    a.clear();
    for (int i=0; i<length && pos<this->array.length(); i++, pos++)
    {
        a.append(this->array.at(pos));
    }

    return a;
}


void TableModel::setAddrFormat(DISPLAY_FORMAT_EN format)
{
    enAddrFormat = format;

    beginResetModel();
    reset();
    endResetModel();
}

void TableModel::setFirstFormat(DISPLAY_FORMAT_EN format)
{
    enFirstFormat = format;

    beginResetModel();
    reset();
    endResetModel();
}

void TableModel::setSecFormat(DISPLAY_FORMAT_EN format)
{
    enSecFormat = format;

    beginResetModel();
    reset();
    endResetModel();
}

void TableModel::setFirstEndian(DISPLAY_ENDIAN_EN format)
{
    enFirstEndian = format;

    beginResetModel();
    reset();
    endResetModel();
}

void TableModel::setSecEndian(DISPLAY_ENDIAN_EN format)
{
    enSecEndian = format;

    beginResetModel();
    reset();
    endResetModel();
}

void TableModel::search(QByteArray bytes, int start)
{
    int index;
    if (bytes.length() <= 0)
    {
        return;
    }

    qDebug() << "start:" << start;

    int count = 0;
    index = start;
    while(1)
    {
        index = array.indexOf(bytes, index);
        if (index < 0)
        {
            break;
        }

        count++;
        emit searchResult(index);
        index += bytes.length();

        //qDebug() << count << index;
    }

    emit searchEnd(count, start);
}

